// C++ Templates 第十章：模板基本术语

/**
 * @brief 10.1是类模板还是模板类
 */
// 术语区分
// 1.类模板(Class Template)：
// 指的是模板本身，是生成类的"蓝图"
// 例如：template<typename T> class Stack { ... };
// 类模板不是类，而是用来生成类的模板

// 2.模板类(Template Class)：
// 指的是从类模板实例化得到的具体类
// 例如：Stack<int>, Stack<std::string>
// 模板类是一个完整的类，有具体的类型

// 正确使用术语
// 这是一个类模板
template <typename T>
class Vector
{
    // ...
};

// 这些是模板类
Vector<int> intVector;
Vector<double> doubleVector;

/**
 * @brief 10.2 替换、实例化和特化
 */
// 替换(Substitution)
// 替换是将模板参数替换为实际类型或值的过程：
template <typename T>
T max(T a, T b)
{
    return a > b ? a : b;
}

// 替换：T → int
int result = max(10, 20);

// 实例化(Instantiation)
// 实例化是基于替换生成具体代码的过程：
// 1.隐式实例化：
// 编译器自动实例化max<int>
int result = max(10, 20);

// 2.显式实例化：
// 显式要求编译器生成max<double>
template double max<double>(double, double);

// 特化(Specialization)
// 特化是为特定类型提供自定义实现：
// 1.全特化：
template <>
class Vector<bool>
{
    // 针对bool类型的特殊实现
};

// 偏特化：
template <typename T>
class Vector<T *>
{
    // 针对所有指针类型的特殊实现
};

/**
 * @brief 10.3 声明和定义
 */
// 模板声明
// 模板声明告诉编译器模板的存在，但不提供实现：
// 函数模板声明
template <typename T>
T max(T a, T b);

// 类模板声明
template <typename T>
class Stack;

// 模板定义
// 模板定义提供完整实现：
// 函数模板定义
template <typename T>
T max(T a, T b)
{
    return a > b ? a : b;
}

// 类模板定义
template <typename T>
class Stack
{
public:
    void push(const T &elem);
    T pop();

private:
    std::vector<T> elems;
};

/**
 * @brief 10.3.1 完整类型和非完整类型
 */
// 完整类型(Complete Type)
// 完整类型是编译器知道其大小和内存布局的类型：
class Person
{
    std::string name;
    int age;
}; // Person是完整类型

template <typename T>
class Container
{
    T value; // 要求T是完整类型
};

// 非完整类型(Incomplete Type)
// 非完整类型是已声明但未定义的类型：
class Forward; // Forward是非完整类型

template <typename T>
class LinkedList
{
    T *data; // T可以是非完整类型
    LinkedList *next;
};
// 在模板中的应用
template <typename T>
class SmartPtr
{
private:
    T *ptr; // T可以是非完整类型
public:
    T &operator*()
    {
        return *ptr; // 但这里需要T是完整类型
    }
};

/**
 * @brief 10.4 单一定义规则(ODR)
 */
// ODR基本规则
// 1.非内联实体：
//      每个程序中只能有一个定义
// 2.内联函数和变量：
//      可以在多个编译单元中有相同定义
//      所有定义必须完全相同

// 模板的ODR规则
// 1.模板定义：
//      模板可以在多个编译单元中定义
//      所有定义必须完全相同
//      通常在头文件中定义
// 2.模板实例：
//      每个程序中，特定模板实例只能有一个定义
//      链接器负责合并相同的模板实例

/**
 * @brief 10.5 模板实参(Template Arguments)
 */
// 模板实参是替换模板形参的具体值：
// 1.类型实参：
Vector<int> v; // int是类型实参
// 2.非类型实参：
Array<10> a; // 10是非类型实参
// 3.模板模板实参：
Adapter<std::vector> adapter; // std::vector是模板模板实参